#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import os
import time
import subprocess

############ from mie.timediff import * ##############
from datetime import datetime, timedelta
def timemake(n=None, y=None, r=None, s=None, f=None, m=None, w=None):
    """
    timemake(y=1, r="2", s="-1", f="+2") =>
        month = 1
        day = 2
        hour = now_hour - 1
        minute = now_minute + 2
    hour: 2, minute: +70 => hour: 3, minute: + 10
    """
    now = datetime.now()

    nn_delta = None
    yy_delta = None
    rr_delta = None
    ss_delta = None
    ff_delta = None
    mm_delta = None
    ww_delta = None

    def getdelta(x):
        if x is None:
            return None

        if str(x)[0] in ("+-"):
            return int(x)

        return None

    nn_delta = getdelta(n)
    if nn_delta is not None:
        nn = now.year + nn_delta
    elif y is None:
        nn = now.year
    else:
        nn = int(n)

    yy_delta = getdelta(y)
    if yy_delta is not None:
        yy = now.month + yy_delta
        nn += int(yy_delta / 12)
        yy = int((yy - 1) % 12) + 1
    elif y is None:
        yy = now.month
    else:
        yy = int(y)

    rr_delta = getdelta(r)
    if rr_delta is not None or r is None:
        rr = now.day
    else:
        rr = int(r)

    ss_delta = getdelta(s)
    if ss_delta is not None or s is None:
        ss = now.hour
    else:
        ss = int(s)

    ff_delta = getdelta(f)
    if ff_delta is not None or f is None:
        ff = now.minute
    else:
        ff = int(f)

    mm_delta = getdelta(m)
    if mm_delta is not None or m is None:
        mm = now.second
    else:
        mm = int(m)

    ww_delta = getdelta(w)
    if ww_delta is not None or w is None:
        ww = now.microsecond
    else:
        ww = int(w)

    days = rr_delta if rr_delta is not None else 0
    hours = ss_delta if ss_delta is not None else 0
    minutes = ff_delta if ff_delta is not None else 0
    seconds = mm_delta if mm_delta is not None else 0
    microseconds = ww_delta if ww_delta is not None else 0
    tmdelta = timedelta(
        days=days,
        hours=hours,
        minutes=minutes,
        seconds=seconds,
        microseconds=microseconds,
    )

    ret = datetime(nn, yy, rr, ss, ff, mm, ww) + tmdelta
    return ret


def timediff(n=None, y=None, r=None, s=None, f=None, m=None, w=None):
    """Time diff to now"""
    delta = timemake(n, y, r, s, f, m, w) - datetime.now()
    seconds = delta.total_seconds()
    return seconds


############ from mie.cmdsplit import cmdSplit ##############
class cmdSplit:
    def __init__(self, segs):
        self.segs = segs
        self.name = self.envs = self.opts = self.args = None
        self.split()

    def opts_nth(self, name, nth, defv=None):
        try:
            val = self.opts.get(name, [])[nth]
            if isinstance(defv, (int, bool, float)):
                return type(defv)(val)
            return val
        except:
            return defv

    def args_nth(self, name, nth, defv=None):
        try:
            val = self.args[nth]
            if isinstance(defv, (int, bool, float)):
                return type(defv)(val)
            return val
        except:
            return defv

    def split(self):
        """Split command line segements to command, envs, opts, args

        cmdline = input()
        segs = shlex.split(cmdline)
        name, envs, opts, args = args_split(segs)

        aaa=AAA bbb=BBB ccc --ddd=DDD --eee EEE --ddd hehe -- --fff FFF ggg kkk
        > envs: { aaa:AAA, bbb:BBB }
        > name: ccc
        > opts: [ {ddd:DDD}, {eee:EEE}, {ddd:hehe}, ... ]
        > args: [ --fff, FFF, ggg, kkk ]
        """

        segs = self.segs
        envs = {}
        name = None
        opts = {}
        args = []

        # Load global environ
        for k, v in os.environ.items():
            envs[k] = v

        segc = len(segs)
        if not segc:
            return

        i = 0

        # envs stage
        while i < segc:
            seg = segs[i]

            if seg.find("=") < 0:
                break

            env = seg.split("=", 1)
            envs[env[0]] = env[1]
            i += 1

        # name stage
        name = segs[i]
        i += 1

        # opts / segs
        while i < segc:
            seg = segs[i]
            i += 1

            # Everything after -- are args
            if seg == "--":
                # Eat all and quit
                args.extend(segs[i:])
                break

            if seg.startswith("--"):
                # --opt aaa --opt bbb arga argb ...

                subsegs = seg.split("=", 1)
                if len(subsegs) > 1:
                    # --lib=xxx.so

                    opt, val = subsegs
                else:
                    # --lib xxx.so

                    if i >= segc:
                        break

                    opt = seg
                    val = segs[i]

                    i += 1

                k = opt[2:]
                v = opts.get(k, [])
                v.append(val)
                opts[k] = v
            elif seg.startswith("-") and len(seg) > 1:
                # boolean opt:
                # cmd -EnableColor -mute
                # cmd -no-EnableColor -no-mute
                if seg.startswith("-no-") and len(seg) > 4:
                    k = seg[4:]
                    v = opts.get(k, [])
                    v.append(False)
                    opts[k] = v
                else:
                    k = seg[1:]
                    v = opts.get(k, [])
                    v.append(True)
                    opts[k] = v
            else:
                # cmd --aaa AAA xixi --bbb=BBB

                # xixi: args
                args.append(seg)

        self.name = name
        self.envs = envs
        self.opts = opts
        self.args = args


cmdparts = cmdSplit(sys.argv)


###############################################################
###############################################################
###############################################################


def help():
    print("usage: runat --n x --y x --r x --s x --f x --m x cmd args ...")
    sys.exit(0)


def main():
    '''usage: runat --n --y --r --s --f --m '''
    # hour +2 3 => h = 3
    # s:1 m:+2000
    # runat --f +5 gedit
    # => runat --runat "go@2017/33/55 23:23:22" --wait seconds -- command

    if "--help" in sys.argv:
        help()

    cmd = cmdSplit(sys.argv)
    cmdName = cmd.name

    # => runat --runat "go@2017/33/55 23:23:22" --wait seconds -- command
    wait = cmd.opts_nth("wait", 0)
    if wait is not None:
        wait = float(wait)
        time.sleep(wait)
        subprocess.call(cmd.args, shell=True)
    else:
        n = cmd.opts_nth("n", 0)
        y = cmd.opts_nth("y", 0)
        r = cmd.opts_nth("r", 0)
        s = cmd.opts_nth("s", 0)
        f = cmd.opts_nth("f", 0)
        m = cmd.opts_nth("m", 0)

        runat = timemake(n, y, r, s, f, m, w="+0")
        delta = runat - datetime.now()
        diff = delta.total_seconds()

        if diff <= 0:
            sys.exit(0)

        cmdSegs = []
        cmdSegs.append(cmdName)
        cmdSegs.append("--runat")
        cmdSegs.append("'%s'" % runat)
        cmdSegs.append("--wait")
        cmdSegs.append(str(diff))
        cmdSegs.append("--")
        cmdSegs.extend(cmd.args)

        os.execv(cmdName, cmdSegs)
        sys.exit(0)

if __name__ == "__main__":
    try:
        main()
    except:
        help()
